package vip.liux.backend.infrastructure.jpa.pay;

import jakarta.persistence.criteria.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import vip.liux.contracts.models.pay.PayWallet;
import vip.liux.contracts.repositories.pay.PayWalletRepository;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public interface PayWalletJpaRepository extends JpaRepository<PayWallet, Long>, PayWalletRepository, JpaSpecificationExecutor<PayWallet> {
    @Query("UPDATE PayWallet w SET w.balance = w.balance - :price, w.freezePrice = w.freezePrice + :price WHERE w.id = :id AND w.balance >= :price")
    @Transactional
    @Modifying
    @Override
    int freezePrice(Long id, BigDecimal price);

    @Query("UPDATE PayWallet w SET w.balance = w.balance + :price, w.freezePrice = w.freezePrice - :price WHERE w.id = :id AND w.freezePrice >= :price")
    @Transactional
    @Modifying
    @Override
    int unFreezePrice(Long id, BigDecimal price);

    @Override
    default Page<PayWallet> findPage(String uid, Pageable page) {
        return findAll((root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotBlank(uid)) {
                predicates.add(criteriaBuilder.equal(root.get("uid"), uid));
            }
            return query.where(predicates.toArray(new Predicate[0])).getRestriction();
        }, page);
    }

    @Query("UPDATE PayWallet w SET w.balance = w.balance - :price, w.totalExpense = w.totalExpense + :price WHERE w.id = :id AND w.balance >= :price")
    @Transactional
    @Modifying
    @Override
    int updateWhenConsumption(Long id, BigDecimal price);

    @Query("UPDATE PayWallet w SET w.balance = w.balance + :price, w.totalRecharge = w.totalRecharge + :price WHERE w.id = :id")
    @Transactional
    @Modifying
    @Override
    int updateWhenRechargeRefund(Long id, BigDecimal price);

    @Query("UPDATE PayWallet w SET w.balance = w.balance + :price, w.totalExpense = w.totalExpense - :price WHERE w.id = :id")
    @Transactional
    @Modifying
    @Override
    void updateWhenConsumptionRefund(Long id, BigDecimal price);

    @Query("UPDATE PayWallet w SET w.balance = w.balance + :price, w.totalRecharge = w.totalRecharge + :price WHERE w.id = :id")
    @Transactional
    @Modifying
    @Override
    void updateWhenRecharge(Long id, BigDecimal price);

    @Query("UPDATE PayWallet w SET w.balance = w.balance + :price WHERE w.id = :id")
    @Transactional
    @Modifying
    @Override
    void updateWhenAdd(Long id, BigDecimal price);
}